Add a transform() method to Path and segments - #101
Conversation
8920910 to
c119d0f
Compare
|
Skews don't work right on curves yet. |
|
This won't work on arcs. It's simply not enough to convert the arc start and end points. If you, for example apply a scale by -1 you must invert the sweep flag, a bit of a rotation would require that you actually change the rotation bit but only if the arc is sort of non-circular. I don't even think I got arcs that work correctly with skews. Since I opted for an internal parameterization of |
|
Good point about the sweep flag, I hadn't thought about that. I think arcs might have to be beziers when skewing, but I haven't looked at getting beziers right yet. |
|
I don't really see how you re-parameterize it afterwards. You could certainly replace the arcs with cubic or quads and those would skew perfectly fine. I think you actually need to solve it as a pretty large and complex equation. Given these values what does this matrix do to each of these values. My solution of just turning (https://www.w3.org/TR/SVG2/implnote.html#ArcParameterizationAlternatives) I think you might need to basically convert the formula with regards to t for the entire svg arc. Multiply it by your particular matrix and them simplify it back to arc values perhaps with values I believe it may actually be akin to: Which is a very useful set of equations to do 3x3 matrix perspective warping mapping 4 points to another 4 points. Which was done using lean. But, in theory you need to know how the matrix affects each value of the parameterization. |
|
Yeah, you are right, I drew out some skewed shapes yesterday and I thought the beziers looked bad, but now I have written tests that confirm them point by point, and they are actually fine, it's only the arcs that are the problem. I guess the nicest would be to somehow apply the matrix in a way that changes the ellipticity (is that a word) and rotates them to make a skew. But I'm not 100% sure that would work, and yeah, the easiest is probably just to convert the arcs to beziers and skew later. I'll think about that after some more coffee. |
|
Looks like it is doable, once you decode the arcane maths: https://math.stackexchange.com/questions/2068583/when-you-skew-an-ellipse-how-do-you-calculate-the-angle-of-rotation-and-the-new |
|
Yeah, I would prefer source code in Klingon to the answer in mathy-english. What's annoying is the person answering that question could probably write the five lines of code it would take. But, convincing them to help make a computer do a practical thing takes a distant 2nd fiddle to explaining the obviousness of the conjectures involved. I've gone pretty deep into learning some Here's an ellipse with a skew applied and a perspective applied to that (inkscape, skew, object to path, path effects, perspective). As you obviously guess there's no There should entirely be a set of equations that explains what happens to each of the arc parameters when you feed the arc into an affine matrix. Start: transformed.
|
|
There's no g and h in SVG, though, so I don't need to implement them, luckily. If the interface doesn't return a new PathSegment, but a list of new PathSegments, that's at least theoretically doable. But I doubt very many people are going to use this transform function at all. I basically just want to close the two last tickets. :-D I'm not sure if there is an order defined for the functions, when you implement a matrix, though. A shear and then rotate would be different from a rotate and then a shear... I'll have to read through the SVG spec to see if there's an order defined. |
8704615 to
c8e4a18
Compare
|
Okay, yes. If somebody calls shear/rotate for your arc, return some bezier curves for that. That actually sounds approximately great. The order is pre-cat in the list. So > from svgelements import *
> Matrix("rotate(5)") * Matrix("translate(20,20)") == Matrix("translate(20, 20) rotate(5)")
True
> m = Matrix("translate(20, 20) rotate(5)")
> m = Matrix()
> m.pre_translate(20,20)
> m.pre_rotate(Angle.degrees(5))
> m == "translate(20, 20) rotate(5)"
True
> Matrix() * "translate(20,20)" * "rotate(5)" == "translate(20,20) rotate(5)"
FalseOr at least that's what was needed to pass the test my Basically But you're probably good if you do matrix parsing tests. And ensure that the orders match. WC3: |
|
Well, suddenly while testing an x-skew and a y-skew created a rotation, but the wrong direction, so yeah, mine brain is definitely struggling. But it's going forward. |
ac7aa53 to
c34d5c9
Compare
c34d5c9 to
c02e252
Compare
* tests: Use better than nothing font Pillow 10.1.0 uses a version of Aileron Regular instead of the previous “better than nothing” default font (in case FreeType support is available). This font change changes the resulting bitmap. Use the "better than nothing" font to keep the expected result identical. The proper solution is either to use one specific font in svg.path or make pillow support loading the “better than nothing” default font. Bug-Debian: https://bugs.debian.org/1055159 * Maintenance --------- Co-authored-by: Benjamin Drung <benjamin.drung@canonical.com>
* Added type annotations to svg.path. All source code and tests pass the `mypy --strict` checks. * Fix tests for python 3.8 and 3.11. * Update after merge --------- Co-authored-by: udifuchs <udifuchs@gmail.com>
For better type annotations
Co-authored-by: udifuchs



No description provided.